package com.tsx.millions.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;

import java.io.OutputStream;
import java.util.List;

/**
 * 【核心武器】分页写入Excel工具 - 专治各种不服(OOM)
 */
public class PageWriteExcelHelper<T> {

    // 🎯 关键接口：定义如何分页获取数据 (由调用方实现)
    public interface PageQuerySupplier<T> {
        List<T> getPage(int pageNum, int pageSize); // 第几页? 每页几条?
    }

    /**
     * 执行分页写入
     *
     * @param outputStream 输出流 (响应OutputStream)
     * @param head         数据模型Class (如 User.class)
     * @param pageSize     【重要】每批次处理条数 (建议 1000~5000)
     * @param totalCount   总数据量 (用于计算总页数)
     * @param supplier     分页数据提供器 (你的业务查询逻辑)
     * @param sheetName    Sheet 名称 (可选，如果为空则使用默认名称)
     * @param perSheetRows 每个Sheet的最大行数 (可选，如果为负数则默认全部写入一个Sheet)
     */
    public static <T> void writeByPage(OutputStream outputStream,
                                       Class<T> head,
                                       int pageSize,
                                       int totalCount,
                                       PageQuerySupplier<T> supplier,
                                       String sheetName,
                                       int perSheetRows) {
        // 🔧 1. 初始化 ExcelWriter (EasyExcel 核心写入器)
        ExcelWriter excelWriter = EasyExcel.write(outputStream, head).build();
        String defaultSheetName = "Sheet1";
        if (sheetName == null || sheetName.isEmpty()) {
            sheetName = defaultSheetName;
        }

        try {
            // 📐 2. 计算总页数 (小心除0)
            int totalPage = totalCount > 0 ? (int) Math.ceil((double) totalCount / pageSize) : 1;

            // 🔁 3. 分页循环：查询 -> 写入 -> 释放
            int currentSheetIndex = 0;
            int currentSheetRow = 0;
            WriteSheet currentSheet = EasyExcel.writerSheet(currentSheetIndex, sheetName + (currentSheetIndex + 1)).build();

            for (int pageNum = 1; pageNum <= totalPage; pageNum++) {
                // 🚚 3.1 获取当前页数据 (你的分页查询)
                List<T> pageData = supplier.getPage(pageNum, pageSize);

                // ✍️ 3.2 写入当前页到 Excel
                excelWriter.write(pageData, currentSheet);

                // 更新当前Sheet的行数
                currentSheetRow += pageData.size();

                // 🗑️ 3.3 【关键】立即清空释放当前页内存！
                pageData.clear();

                // 判断是否需要切换Sheet
                if (perSheetRows > 0 && currentSheetRow >= perSheetRows) {
                    currentSheetIndex++;
                    currentSheetRow = 0;
                    currentSheet = EasyExcel.writerSheet(currentSheetIndex, sheetName + (currentSheetIndex + 1)).build();
                }
            }
        } finally {
            // 🔒 4. 【务必关闭】释放资源 (防止内存泄漏)
            if (excelWriter != null) {
                excelWriter.finish(); // 重要！！！
                excelWriter.close();
            }
        }
    }
}
